import { EOF, Parser, StateFn } from './parser';

export class ChunkedBodyParser extends Parser {
  protected state: StateFn = this.WAITING_LENGTH;

  private length: number = 0;
  public content: string[] = [];

  private WAITING_LENGTH(char: string | typeof EOF) {
    switch (char) {
      case '\r': {
        if (this.length === 0) {
          this.isFinished = true;
        }

        return this.WAITING_LENGTH_LINE_END;
      }

      case EOF: {
        return this.END;
      }

      default: {
        if (typeof char === 'string') {
          this.length *= 16;
          this.length += parseInt(char, 16);
        }

        return this.WAITING_LENGTH;
      }
    }
  }

  private WAITING_LENGTH_LINE_END(char: string | typeof EOF) {
    switch (char) {
      case '\n': {
        return this.READING_TRUNK;
      }
    }
  }

  private READING_TRUNK(char: string | typeof EOF) {
    // consume '\r' when the length of last trunk is 0
    if (this.isFinished && this.length === 0) {
      return this.WAITING_NEW_LINE(char);
    }

    if (typeof char === 'string') {
      this.content.push(char);
    }

    this.length--;

    if (this.length === 0) {
      return this.WAITING_NEW_LINE;
    }

    return this.READING_TRUNK;
  }

  private WAITING_NEW_LINE(char: string | typeof EOF) {
    switch (char) {
      case '\r': {
        return this.WAITING_NEW_LINE_END;
      }
    }
  }

  private WAITING_NEW_LINE_END(char: string | typeof EOF) {
    switch (char) {
      case '\n': {
        return this.WAITING_LENGTH;
      }
    }
  }

  private END(char: string | typeof EOF) {
    return;
  }
}